Skip to content

🔧 update: inject sender userId into LLM context so owner is correctly identified via web dashboard#85

Closed
warengonzaga wants to merge 4 commits into
devfrom
pr84
Closed

🔧 update: inject sender userId into LLM context so owner is correctly identified via web dashboard#85
warengonzaga wants to merge 4 commits into
devfrom
pr84

Conversation

@warengonzaga

Copy link
Copy Markdown
Owner

When the owner interacts through the web dashboard, the LLM was misidentifying them as a "friend" and refusing owner-only actions (e.g., changing the companion's name). The system prompt declared as the owner userId, but no userId was ever passed alongside incoming messages — leaving the LLM to guess, and incorrectly infer that a web session couldn't be .

Change


  • Added to strip backticks, square brackets, and newlines from before embedding it in any prompt, preventing a crafted from breaking the marker format or injecting additional instructions.
  • Sender identity is now appended directly to the system prompt for the turn rather than injected as a separate message immediately before the user message. This ensures the identity covers the entire turn — including all tool-follow-up user messages — without needing per-message injection.

[Current message sender: userId = ]\n\n[Current message sender: userId = ]


  • Added assertions that the marker is present in the system prompt content and that the immediately following message is the user turn (no separate system entry in between).
  • Existing tool-summary / assertions remain correct and unchanged.

The passed here is resolved server-side from , so the LLM now has a ground-truth sender identity to match against the in the system prompt — regardless of which channel the message arrived through.

Copilot AI and others added 4 commits May 20, 2026 11:51
- add detailed comment explaining stripping of backticks, brackets, newlines
- add comprehensive unit test suite covering edge cases
Copilot AI review requested due to automatic review settings May 26, 2026 13:26
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.


root seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

Comment thread packages/core/src/loop.ts
* Newlines (\n\r) are stripped to prevent multi-line injection.
*/
function sanitizeUserIdForPrompt(userId: string): string {
return userId.replace(/[`\\[\\]\\n\\r]/g, '');
expect(sanitizeUserIdForPrompt('`[\\n\\r]')).toBe('');
});
});
};// This is to close the outer describe block that was truncated in the initial read

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR ensures the LLM can reliably distinguish owner vs. friend actions by embedding the current message sender userId directly into the system prompt for each agent loop turn, and adds sanitization to prevent marker-format/prompt injection via crafted userIds.

Changes:

  • Append a [Current message sender: userId = \...`]` marker to the system prompt each turn (instead of relying on separate per-message injection).
  • Add sanitizeUserIdForPrompt() to strip backticks, brackets, and newlines before embedding userId in the system prompt.
  • Update/add tests to assert sender identity presence in the system prompt (but current test changes introduce syntax/runtime issues that must be fixed).

Reviewed changes

Copilot reviewed 2 out of 3 changed files in this pull request and generated 4 comments.

File Description
packages/core/src/loop.ts Adds sanitizeUserIdForPrompt() and appends the sender identity marker to the system prompt in agentLoop().
packages/core/tests/loop.test.ts Adds assertions for the sender marker, and attempts to add unit tests for userId sanitization (currently broken).
bun.lock Updates lockfile dependency resolutions (not directly related to the loop logic changes).

Comment on lines +298 to +311
});
});

describe('sanitizeUserIdForPrompt', () => {
const { sanitizeUserIdForPrompt } = require('../src/loop.js');

test('strips backticks, brackets, and newlines', () => {
expect(sanitizeUserIdForPrompt('test`[id]\n')).toBe('testid');
expect(sanitizeUserIdForPrompt('normal-id')).toBe('normal-id');
expect(sanitizeUserIdForPrompt('')).toBe('');
expect(sanitizeUserIdForPrompt('`[\\n\\r]')).toBe('');
});
});
};// This is to close the outer describe block that was truncated in the initial read
expect(sanitizeUserIdForPrompt('`[\\n\\r]')).toBe('');
});
});
};// This is to close the outer describe block that was truncated in the initial read
Comment on lines +301 to +311
describe('sanitizeUserIdForPrompt', () => {
const { sanitizeUserIdForPrompt } = require('../src/loop.js');

test('strips backticks, brackets, and newlines', () => {
expect(sanitizeUserIdForPrompt('test`[id]\n')).toBe('testid');
expect(sanitizeUserIdForPrompt('normal-id')).toBe('normal-id');
expect(sanitizeUserIdForPrompt('')).toBe('');
expect(sanitizeUserIdForPrompt('`[\\n\\r]')).toBe('');
});
});
};// This is to close the outer describe block that was truncated in the initial read
Comment on lines +301 to +303
describe('sanitizeUserIdForPrompt', () => {
const { sanitizeUserIdForPrompt } = require('../src/loop.js');

@warengonzaga

Copy link
Copy Markdown
Owner Author

Not needed, closing this.

@warengonzaga warengonzaga deleted the pr84 branch June 1, 2026 08:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants